﻿//---------------------------------------------------------------------------------
// Copyright 2011 Microsoft Corporation
// Licensed under the Microsoft Public License (MS-PL) (the "License"); 
// You may not use this file except in compliance with the License. 
// You may obtain a copy of the License at http://www.opensource.org/licenses/ms-pl.html
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR 
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, 
// INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR 
// CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
// MERCHANTABLITY OR NON-INFRINGEMENT. 
// See the Microsoft Public License (MS-PL) for the specific language governing 
// permissions and limitations under the License.
//---------------------------------------------------------------------------------

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using System.Windows.Browser;

namespace Microsoft.Telco.Controls
{
    /// <summary>
    /// Control that displays advertisement in an application.
    /// </summary>
    #region Parts and States Model Declarations
    [TemplatePart(Name = "AdvControlBorder", Type = typeof(Border))]
    [TemplatePart(Name = "AdvImage", Type = typeof(Image))]
    [TemplatePart(Name = "AdvText", Type = typeof(TextBlock))]
    [TemplateVisualState(Name = "DisplayImage", GroupName = "LoadStates")]
    [TemplateVisualState(Name = "DisplayText", GroupName = "LoadStates")]
    [TemplateVisualState(Name = "Normal", GroupName = "LoadStates")]
    #endregion
    public class AdvertisingControl : TelcoControlBase
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="AdvertisingControl"/> class.
        /// </summary>
        public AdvertisingControl()
        {
            this.DefaultStyleKey = typeof(AdvertisingControl);
        }       

        /// <summary>
        /// When overridden in a derived class, is invoked whenever application code or internal processes (such as a rebuilding layout pass) call <see cref="M:System.Windows.Controls.Control.ApplyTemplate"/>.
        /// </summary>
        public override void OnApplyTemplate()
        {
            RootBorder = this.GetTemplateChild("AdvControlBorder") as Border;
            if (RootBorder != null)
            {
                RootBorder.MouseLeftButtonDown -= RootBorder_MouseLeftButtonDown; // try to remove the existing sink so that we don't call the event more than once.
                RootBorder.MouseLeftButtonDown += RootBorder_MouseLeftButtonDown;
            }
            AdvMessageTextblock = this.GetTemplateChild("AdvText") as TextBlock;
            AdvImage = this.GetTemplateChild("AdvImage") as Image;
            if (AdvImage != null)
            {
                AdvImage.ImageFailed += AdvImage_ImageFailed;
            }

            UpdateAdvertisement(false);

            if (this.AutoUpdate && this.UpdateInterval > 0)
            {
                SetAdverisementToUpdate();
            }
        }

        #region parts
        /// <summary>
        /// Gets or sets the root border.
        /// </summary>
        /// <value>The root border.</value>
        public Border RootBorder { get; set; }

        /// <summary>
        /// Gets or sets the advertising message textblock.
        /// </summary>
        /// <value>The adv message textblock.</value>
        public TextBlock AdvMessageTextblock { get; set; }

        /// <summary>
        /// Gets or sets the advertising image.
        /// </summary>
        /// <value>The adv image.</value>
        public Image AdvImage { get; set; }
        #endregion

        #region properties
        /// <summary>
        /// Gets or sets the the source of the image to be shown.
        /// </summary>
        /// <value>The advertisement image source.</value>
        public string AdvertisementImageSrc { get; set; }

        /// <summary>
        /// Gets or sets the advertisement image atl text. This gets displayed if image fails to load.
        /// </summary>
        /// <value>The advertisement image atl text.</value>
        public string AdvertisementImageAtlText { get; set; }

        /// <summary>
        /// Gets or sets the the source of the image to be shown.
        /// </summary>
        /// <value>The advertisement text.</value>
        public string AdvertisementText { get; set; }

        /// <summary>
        /// Gets or sets the navigate URL.
        /// </summary>
        /// <value>The URL to navigate to when the advertisement is clicked.</value>
        public string NavigateUrl { get; set; }

        /// <summary>
        /// Gets or sets the advertisement mode.
        /// </summary>
        /// <value>The advertisement mode.</value>
        public AdvertisementMode AdvertisementMode { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether [auto update]. True if advertisement updates after an interval
        /// </summary>
        /// <value><c>true</c> if [auto update]; otherwise, <c>false</c>.</value>
        public bool AutoUpdate { get; set; }

        /// <summary>
        /// Time in miliseconds in which to update the advertisement
        /// </summary>
        /// <value>The update interval.</value>
        public double UpdateInterval { get; set; }
        #endregion

        #region dependency properties
        /// <summary>
        /// Gets or sets the AdvertisementTextForeground for AdvertisingControl.
        /// </summary>
        /// <value>The AdvertisementTextForeground.</value>
        public Brush AdvertisementTextForeground
        {
            get { return (Brush)GetValue(AdvertisementTextForegroundProperty); }
            set { SetValue(AdvertisementTextForegroundProperty, value); }
        }

        /// <summary>
        /// This DependencyProperty acts as the backing store for AdvertisementTextForeground for AdvertisingControl.  This enables animation, styling, binding, etc.
        /// </summary>
        public static readonly DependencyProperty AdvertisementTextForegroundProperty =
            DependencyProperty.Register("AdvertisementTextForeground", typeof(Brush), typeof(AdvertisingControl),
            new PropertyMetadata(new SolidColorBrush(Colors.White),
                        new PropertyChangedCallback((obj, args) =>
                        {
                            AdvertisingControl control = (AdvertisingControl)obj;
                            if (control.AdvMessageTextblock != null)
                            {
                                control.AdvMessageTextblock.Foreground = args.NewValue as Brush;
                            }
                        })));


        /// <summary>
        /// Gets or sets the AdvertisementTextFontFamily for AdvertisingControl.
        /// </summary>
        /// <value>The AdvertisementTextFontFamily.</value>
        public FontFamily AdvertisementTextFontFamily
        {
            get { return (FontFamily)GetValue(AdvertisementTextFontFamilyProperty); }
            set { SetValue(AdvertisementTextFontFamilyProperty, value); }
        }

        /// <summary>
        /// This DependencyProperty acts as the backing store for AdvertisementTextFontFamily for AdvertisingControl.  This enables animation, styling, binding, etc.
        /// </summary>
        public static readonly DependencyProperty AdvertisementTextFontFamilyProperty =
            DependencyProperty.Register("AdvertisementTextFontFamily", typeof(FontFamily), typeof(AdvertisingControl),
            new PropertyMetadata(new FontFamily("Portable User Interface"),
                        new PropertyChangedCallback((obj, args) =>
                        {
                            AdvertisingControl control = (AdvertisingControl)obj;
                            if (control.AdvMessageTextblock != null)
                            {
                                control.AdvMessageTextblock.FontFamily = args.NewValue as FontFamily;
                            }
                        })));


        /// <summary>
        /// Gets or sets the AdvertisementTextFontWeight for AdvertisingControl.
        /// </summary>
        /// <value>The AdvertisementTextFontWeight.</value>
        public FontWeight AdvertisementTextFontWeight
        {
            get { return (FontWeight)GetValue(AdvertisementTextFontWeightProperty); }
            set { SetValue(AdvertisementTextFontWeightProperty, value); }
        }

        /// <summary>
        /// This DependencyProperty acts as the backing store for AdvertisementTextFontWeight for AdvertisingControl.  This enables animation, styling, binding, etc.
        /// </summary>
        public static readonly DependencyProperty AdvertisementTextFontWeightProperty =
            DependencyProperty.Register("AdvertisementTextFontWeight", typeof(FontWeight), typeof(AdvertisingControl),
            new PropertyMetadata(FontWeights.Normal,
                        new PropertyChangedCallback((obj, args) =>
                        {
                            AdvertisingControl control = (AdvertisingControl)obj;
                            if (control.AdvMessageTextblock != null)
                            {
                                control.AdvMessageTextblock.FontWeight = (FontWeight)args.NewValue;
                            }
                        })));


        /// <summary>
        /// Gets or sets the AdvertisementTextFontSize for AdvertisingControl.
        /// </summary>
        /// <value>The AdvertisementTextFontSize.</value>
        public double AdvertisementTextFontSize
        {
            get { return (double)GetValue(AdvertisementTextFontSizeProperty); }
            set { SetValue(AdvertisementTextFontSizeProperty, value); }
        }

        /// <summary>
        /// This DependencyProperty acts as the backing store for AdvertisementTextFontSize for AdvertisingControl.  This enables animation, styling, binding, etc.
        /// </summary>
        public static readonly DependencyProperty AdvertisementTextFontSizeProperty =
            DependencyProperty.Register("AdvertisementTextFontSize", typeof(double), typeof(AdvertisingControl),
            new PropertyMetadata(16.0D,
                        new PropertyChangedCallback((obj, args) =>
                        {
                            AdvertisingControl control = (AdvertisingControl)obj;
                            if (control.AdvMessageTextblock != null)
                            {
                                control.AdvMessageTextblock.FontSize = (double)args.NewValue;
                            }
                        })));

        #endregion

        #region event handlers
        /// <summary>
        /// Handles the MouseLeftButtonDown event of the RootBorder control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
        protected void RootBorder_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            //Navigate
            if (!string.IsNullOrEmpty(this.NavigateUrl))
            {
                RootBorder.Cursor = Cursors.Hand;
                if (ControlHelper.IsWindowsPhone)
                {
                    //WebBrowserTask webBrowserTask = new WebBrowserTask();
                    //webBrowserTask.URL = this.NavigateUrl;
                    //webBrowserTask.Show();
                }
                else
                {
                    HtmlPage.Window.Navigate(new Uri(this.NavigateUrl, UriKind.Absolute),"_blank", "");
                }
            }
        }

        /// <summary>
        /// Handles the ImageFailed event of the AdvImage control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.ExceptionRoutedEventArgs"/> instance containing the event data.</param>
        protected void AdvImage_ImageFailed(object sender, ExceptionRoutedEventArgs e)
        {
            this.AdvMessageTextblock.Text = this.AdvertisementImageAtlText;
            VisualStateManager.GoToState(this, "DisplayText", true);
        }
        #endregion

        #region helper methods
        private void SetAdverisementToUpdate()
        {
            DispatcherTimer timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromMilliseconds(this.UpdateInterval);
            timer.Tick += (s,e) =>
            {
                UpdateAdvertisement(true);
            };
            timer.Start();
        }

        /// <summary>
        /// Updates the advertisement.
        /// </summary>
        /// <param name="useTransitions">if set to <c>true</c> [use transitions].</param>
        public void UpdateAdvertisement(bool useTransitions)
        {
            //Make REST service call here to get values

            switch (this.AdvertisementMode)
            {
                case AdvertisementMode.Image:
                    if (AdvImage != null && !string.IsNullOrEmpty(this.AdvertisementImageSrc))
                    {
                        AdvImage.Source = new BitmapImage(new Uri(this.AdvertisementImageSrc, UriKind.RelativeOrAbsolute));
                        VisualStateManager.GoToState(this, "DisplayImage", useTransitions);
                    }
                    break;
                case AdvertisementMode.Text:
                    if (AdvMessageTextblock != null && !string.IsNullOrEmpty(AdvertisementText))
                    {
                        AdvMessageTextblock.Text = AdvertisementText;
                        VisualStateManager.GoToState(this, "DisplayText", useTransitions);
                    }
                    break;
                default:
                    VisualStateManager.GoToState(this, "Normal", useTransitions);
                    break;
            }
        }

        private void UpdateStates(bool useTransitions)
        {
            throw new NotImplementedException();
        }
        #endregion
    }
}
